#include "Console.h"

CConsole::CConsole(void)
:m_hConsole	( INVALID_HANDLE_VALUE )
,m_isLogFile ( false )
,m_logFP( NULL )
,m_curBackColor( 0U )
,m_curColor( 0U )
{
	clear();
}

CConsole::~CConsole(void)
{
	Destroy();
}

CConsole::CConsole( const char * cszTitle )
:m_hConsole	( INVALID_HANDLE_VALUE )
,m_isLogFile ( false )
,m_logFP( NULL )
,m_curBackColor( 0U )
,m_curColor( 0U )
{
	Create( cszTitle );
}


CConsole::CConsole( const char * cszTitle, const char * strLogFilename )
{
	Create( cszTitle, strLogFilename );
}

bool CConsole::Create( const char * cszTitle )
{
	AllocConsole();
	m_hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
	SetConsoleTitleA( cszTitle );

	return m_hConsole != INVALID_HANDLE_VALUE;
}

bool CConsole::Create( const char * cszTitle,
			const char * strLogFileName,
			WORD wInfoMsgColor,
			WORD wWarnMsgColor,
			WORD wErrorMsgColor,
			WORD wEtcMsgColor)
{
	if( false == Create(cszTitle) )
		return false;

	MakeLogFile( strLogFileName );

	SetLogColor( LOG_LEVEL_INFO, wInfoMsgColor );
	SetLogColor( LOG_LEVEL_WARNING, wWarnMsgColor );
	SetLogColor( LOG_LEVEL_ERROR, wErrorMsgColor );
	SetLogColor( LOG_LEVEL_ETC, wEtcMsgColor );
	
	return true;
}

void CConsole::Destroy()
{
	if ( m_logFP )
	{
	}
	if ( m_hConsole != INVALID_HANDLE_VALUE )
	{
		CloseHandle(m_hConsole);
		FreeConsole();
		m_hConsole = INVALID_HANDLE_VALUE;
	}
}

bool CConsole::IsShowLog( unsigned int  iLogType )
{
	if ( iLogType >= LOG_TYPE_MAX_NUM )
		return false;

	return !m_logType[ iLogType ].isHide;
}


void CConsole::SetLogColor( unsigned int iLogType, WORD color )
{
	assert (iLogType < LOG_TYPE_MAX_NUM );
	m_logType[iLogType].color = color;
}

bool CConsole::MakeLogFile( const char* cszFileName )
{
	if ( m_logFP )
	{
		fclose( m_logFP );
		m_logFP = NULL; 
	}

	fopen_s( &m_logFP, cszFileName, "a");

	if ( !m_logFP )
	{
		m_isLogFile = false;
		return false;
	}

	m_isLogFile = true;

	return true;
}

void CConsole::Write( UINT logType, const char*    szFmt ... )
{
	if ( !IsShowLog( logType ))
		return;

		const int c_bufSize = 512;

		if( !m_hConsole )
			return;

		char szOut[ c_bufSize ];

		va_list va;
		va_start(va,szFmt);
		int len = _vsnprintf_s(szOut, c_bufSize, szFmt, va);
		va_end(va);

		if ( len > 0 )
		{
			szOut[len] = 0;

			DWORD	written;

			ApplyBackColor( szOut[0] );
			SetConsoleColor( m_logType[ logType ].color );
			WriteConsoleA( m_hConsole, szOut, len, &written, NULL );

			if ( m_isLogFile )
			{
				fwrite( szOut, len, 1, m_logFP );
				fflush( m_logFP );
			}
		}
}

void CConsole::Write( UINT logType, const wchar_t* szFmt ... )
{
	
	if ( !IsShowLog( logType ))
		return;

	const int c_bufSize = 512;

	if( !m_hConsole )
		return;

	wchar_t szOut[ c_bufSize ];
	memset(szOut,NULL,sizeof(wchar_t));

	va_list va;
	va_start(va,szFmt);
	int len = _vsnwprintf_s(szOut, c_bufSize, szFmt, va);
	va_end(va);

	if ( len > 0 )
	{
		szOut[len] = 0;

		DWORD	written;

		ApplyBackColor( szOut[0] );
		SetConsoleColor( m_logType[ logType ].color );
		WriteConsoleW( m_hConsole, szOut, len, &written, NULL );

		if ( m_isLogFile )
		{
			fwprintf( m_logFP, szOut );
			fflush( m_logFP );
		}
	}
}

void CConsole::Write( const char * szFmt, ... )
{

	const int c_bufsize = 512;

	char szOut[ c_bufsize ];

	va_list va;
	va_start(va, szFmt);
	int len = _vsnprintf_c( szOut, c_bufsize, szFmt, va );
	va_end(va);

	if ( len > 0 )
	{
		szOut[len] = 0;

		DWORD written;

		ApplyBackColor( szOut[0] );
		SetConsoleColor( m_logType[0].color);
		WriteConsoleA( m_hConsole, szOut, len, &written, NULL );

		if ( m_isLogFile )
		{
			fwrite( szOut, len, 1, m_logFP );
			fflush( m_logFP );
		}
	}

}

void CConsole::Write( const wchar_t * szFmt, ... )
{
	const int c_bufSize = 512;

		if( !m_hConsole )
			return;

		wchar_t szOut[c_bufSize];

		va_list va;
		va_start(va,szFmt);
		int len = _vsnwprintf_s(szOut, c_bufSize, szFmt, va);
		va_end(va);

		if ( len > 0 )
		{
			DWORD written;

			szOut[len] = 0;
			ApplyBackColor( szOut[0] );
			SetConsoleColor( m_logType[ 0 ].color );
			WriteConsoleW( m_hConsole, szOut, len, &written, NULL );

			if ( m_isLogFile )
			{
				fwprintf( m_logFP, szOut );
				//fwrite( szOut, len, 1, m_logFP );
				fflush( m_logFP );
			}
		}
}


void CConsole::SetConsoleColor( WORD color )
{
	if( m_curColor != (color | m_curBackColor ))
	{
		m_curColor = ( color | m_curBackColor );

		SetConsoleTextAttribute( m_hConsole, m_curColor );
	}
}	

void CConsole::ApplyBackColor( char cLogFirstByte )
{
		if ( cLogFirstByte == '!' )
		{
			SetBackgroundColor( m_backColor[ LOG_LEVEL_WARNING ] );
		}
		else if ( cLogFirstByte == '#' )
		{
			SetBackgroundColor( m_backColor[ LOG_LEVEL_ERROR ] );
		}
		else if ( cLogFirstByte == '*' )
		{
			SetBackgroundColor( m_backColor[ LOG_LEVEL_INFO ] );
		}
		else
		{
			SetBackgroundColor( m_backColor[ LOG_LEVEL_ETC ] );
		}
}

void CConsole:: SetBackgroundColor( WORD color )
{
	m_curBackColor = color;
}

void CConsole::clear()
{

	m_hConsole	= INVALID_HANDLE_VALUE;
	m_isLogFile	= false;
	m_logFP		= NULL;

	m_curBackColor	= 0;
	m_curColor		= 0;

	m_backColor[ 0 ] = 0;					// etc
	m_backColor[ 1 ] = BACKGROUND_BLUE;		// info
	m_backColor[ 2 ] = BACKGROUND_GREEN;	// warning
	m_backColor[ 3 ] = BACKGROUND_RED;		// error
}